#pragma once

#include <list>
#include <string>
#include <vector>

#include "arm.h"
#include "arminst.h"

struct ArmBlock : public Arm::Printable {
    std::string name;
    std::list<Arm::Inst*> instList;
    std::unordered_map<ArmBlock*, ArmBlock**> prev;

    ArmBlock() {}
    ArmBlock(Arm::Inst* inst) {
        instList.emplace_back(inst);
        inst->parent = this;
    }

    void AddInst(Arm::Inst* inst);

    Arm::Terminator* GetTerminator() const;
    std::vector<ArmBlock*> GetNext() const;
    std::vector<ArmBlock*> GetPrev() const;

    // Connect the block with another block using jump terminator.
    void Connect(ArmBlock* nxt);

    // Connect the block with another block using branch terminator.
    void Connect(ArithOp cond, ArmBlock* t, ArmBlock* f);

    // Remove the block and connect the previous with the reserved block.
    // reserve = 0/1: reserve true/false condition block.
    ArmBlock* Remove(int reserve = -1);

    // Change branch terminator into jump terminator.
    // reserve = 0/1: reserve true/false condition block.
    ArmBlock* RemoveBranch(int reserve = -1);

    void GenAsm(std::ostream& os) const override;
};
